package com.hjzd.ai.smartpractice.util;

import be.tarsos.dsp.SilenceDetector;
import be.tarsos.dsp.io.TarsosDSPAudioFloatConverter;
import be.tarsos.dsp.io.TarsosDSPAudioFormat;
import be.tarsos.dsp.pitch.Yin;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

/**
 * 静音检测工具类
 */
public class SilenceDetectionUtil {

    private static final Logger logger = LoggerFactory.getLogger(SilenceDetectionUtil.class);
    private static final Gson gson = new Gson();

    // 默认音频参数
    private static final float DEFAULT_SAMPLE_RATE = 16000;
    // 位深度
    private static final int DEFAULT_SAMPLE_SIZE_IN_BITS = 16;

    /**
     * 检测音频是否为静音
     *
     * @param audioData 音频数据
     * @return 如果是静音返回 true，否则返回 false
     */
    public static boolean isSilence(byte[] audioData) {
        try {
            // 创建 TarsosDSP 音频格式
            TarsosDSPAudioFormat tdspFormat = new TarsosDSPAudioFormat(
                    DEFAULT_SAMPLE_RATE, DEFAULT_SAMPLE_SIZE_IN_BITS, 1, true, false);

            // 将字节数组转换为浮点数组
            float[] voiceFloatArr = new float[audioData.length / tdspFormat.getFrameSize()];
            TarsosDSPAudioFloatConverter audioFloatConverter = TarsosDSPAudioFloatConverter.getConverter(tdspFormat);
            audioFloatConverter.toFloatArray(audioData, voiceFloatArr);

            // 使用 SilenceDetector 检测静音
            SilenceDetector silenceDetector = new SilenceDetector();
            return silenceDetector.isSilence(voiceFloatArr);
        } catch (Exception e) {
            logger.error("静音检测失败", e);
            return false;
        }
    }

    /**
     * 检测音频是否包含人声
     *
     * @param audioData 音频数据
     * @return 如果包含人声返回 true，否则返回 false
     */
    public static boolean isHumanVoice(byte[] audioData) {
        try {
            // 创建音频格式
            TarsosDSPAudioFormat format = new TarsosDSPAudioFormat(DEFAULT_SAMPLE_RATE, 16, 1, true, false);

            // 创建音高检测器
            Yin pitchDetector = new Yin(DEFAULT_SAMPLE_RATE, 1024);

            // 将字节数组转换为浮点数组
            float[] audioBuffer = new float[audioData.length / 2]; // 16-bit 音频，每个采样点占 2 字节
            TarsosDSPAudioFloatConverter converter = TarsosDSPAudioFloatConverter.getConverter(format);
            converter.toFloatArray(audioData, audioBuffer);

            // 检测音高
            for (int i = 0; i < audioBuffer.length; i += 1024) {
                float[] frame = new float[1024];
                System.arraycopy(audioBuffer, i, frame, 0, Math.min(1024, audioBuffer.length - i));
                float pitch = pitchDetector.getPitch(frame).getPitch();

                // 检查音高是否在人声范围内
                if (pitch > 85 && pitch < 255) {
                    logger.info("检测音高"+pitch);
                    return true;
                }
            }
        } catch (Exception e) {
            logger.error("人声检测失败", e);
        }
        return false;
    }

    /**
     * 发送语音流到语音活动检测服务
     *
     * @param audioBytes 语音流数据
     * @return 如果检测到语音活动返回 true，否则返回 false
     */
    public static boolean sendSpeechToDetectService(byte[] audioBytes) {
        try {
            String url = "http://8.223.15.130:8010/speech_detect";
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            HttpEntity<byte[]> requestEntity = new HttpEntity<>(audioBytes, headers);

            // 发送 POST 请求
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, requestEntity, String.class);

            // 解析响应
            if (responseEntity.getStatusCode().is2xxSuccessful()) {
                String responseBody = responseEntity.getBody();
                // 解析 JSON 响应
                JsonObject jsonResponse = gson.fromJson(responseBody, JsonObject.class);
                if (jsonResponse.has("result") && jsonResponse.get("result").getAsBoolean()) {
                    // 如果检测到语音活动
                    return true;
                } else if (jsonResponse.has("error")) {
                    // 如果服务返回错误
                    logger.error("语音活动检测服务返回错误: {}", jsonResponse.get("error").getAsString());
                    return false;
                }
            } else {
                logger.warn("语音活动检测失败，状态码: {}", responseEntity.getStatusCodeValue());
            }
        } catch (Exception e) {
            logger.error("语音活动检测请求失败", e);
        }

        // 默认返回 false
        return false;
    }


    /**
     * 发送语音流到检测服务
     *
     * @param audioBytes 语音流数据
     * @return 检测结果是否有效
     */
    public static boolean sendVoiceToDetectService(byte[] audioBytes) {
        try {
            String url = "http://8.223.15.130:8010/voice_detect";
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            HttpEntity<byte[]> requestEntity = new HttpEntity<>(audioBytes, headers);
            ResponseEntity<String> responseEntity = new RestTemplate().postForEntity(url, requestEntity, String.class);

            // 解析响应
            if (responseEntity.getStatusCode().is2xxSuccessful()) {
                String responseBody = responseEntity.getBody();
                logger.info("语音流检测成功，响应内容: {}", responseBody);
                JsonObject jsonResponse = gson.fromJson(responseBody, JsonObject.class);
                if (jsonResponse.has("result") && jsonResponse.get("result").getAsBoolean()) {
                    return false;
                } else if (jsonResponse.has("error")) {
                    return true;
                }
            } else {
                logger.warn("语音流检测失败，状态码: {}", responseEntity.getStatusCodeValue());
            }
        } catch (Exception e) {
            logger.error("语音流检测请求失败", e);
        }
        return false;
    }
}
